package com.heima.controller.resident;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.heima.Result;
import com.heima.config.JWTConfig;
import com.heima.context.ResidentContext;
import com.heima.domain.dto.ResidentDTO;
import com.heima.domain.po.Resident;
import com.heima.domain.vo.ResidentVO;
import com.heima.exception.DIYException;
import com.heima.service.IResidentService;
import com.heima.util.JwtUtil;
import com.heima.util.RegexUtils;
import com.heima.util.RedisUtil;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * <p>
 * 居民信息表 前端控制器
 * </p>
 *
 * @author author
 * @since 2025-07-24
 */
@Tag(name = "居民相关接口")
@RestController
@RequestMapping("/resident")
public class ResidentController {
    @Autowired
    private IResidentService residentService;
    @Autowired
    private JWTConfig jwtConfig;
    @Autowired
    private RedisUtil redisUtil;

    private static final String PreKey = "resident:code:";

    @Operation(summary = "居民登录")
    @PostMapping("/login")
    public Result login(@RequestBody ResidentDTO residentDTO) {
        String phone = residentDTO.getPhone();
        String password = residentDTO.getPassword();
        String account = residentDTO.getAccount();
        if ((StrUtil.isBlank(phone) && StrUtil.isBlank(account)) || StrUtil.isBlank(password)) {
            throw new DIYException("手机号、密码或账号不能为空");
        }
        if (password.length() < 6 || password.length() > 16) {
            throw new DIYException("密码长度必须在6到16个字符之间");
        }
        Resident resident = residentService.lambdaQuery()
                .eq(StrUtil.isNotBlank(phone), Resident::getPhone, phone)
                .eq(StrUtil.isNotBlank(account), Resident::getAccount, account)
                .one();
        if (resident == null)
            throw new DIYException("用户不存在");
        if (!resident.getPassword().equals(password))
            throw new DIYException("密码错误");
        ResidentVO residentVO = BeanUtil.copyProperties(resident, ResidentVO.class);
        Map<String, Object> claims = new HashMap<>();
        claims.put("residentId", resident.getId());
        claims.put("account", account);
        String token = JwtUtil.getToken(claims, jwtConfig.getResidentTtl(), jwtConfig.getResidentSecretKey());
        residentVO.setToken(token);
        return Result.success(residentVO);
    }

    @Operation(summary = "居民注册")
    @PostMapping("/register")
    public Result register(@RequestBody ResidentDTO residentDTO) {
        String phone = residentDTO.getPhone();
        String password = residentDTO.getPassword();
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(password)) {
            throw new DIYException("手机号或密码不能为空");
        }
        if (password.length() < 6 || password.length() > 16) {
            throw new DIYException("密码长度必须在6到16个字符之间");
        }
        if (RegexUtils.isPhoneInvalid(phone)) {
            throw new DIYException("手机号格式不正确");
        }
        // 获取居民信息
        Resident resident = residentService.lambdaQuery()
                .eq(Resident::getPhone, phone).one();
        if (resident != null)
            throw new DIYException("手机号已被注册");
        resident = new Resident();
        BeanUtils.copyProperties(residentDTO, resident);
        if (StrUtil.isBlank(resident.getNickname())) {
            // 生成UUID
            UUID uuid = UUID.randomUUID();
            // 转换为字符串并去除横杠
            String uuidWithoutHyphens = uuid.toString().replace("-", "");
            // 截取前8个字符作为昵称
            String nickname = uuidWithoutHyphens.substring(0, 8);
            resident.setNickname("居民_" + nickname);
        }
        resident.setCreateTime(LocalDateTime.now());
        resident.setUpdateTime(LocalDateTime.now());
        residentService.save(resident);
        return Result.success();
    }

    @Operation(summary = "获取手机验证码")
    @PostMapping("/getCode")
    public Result getCode(@RequestBody ResidentDTO residentDTO) {
        String phone = residentDTO.getPhone();
        if (StrUtil.isBlank(phone)) {
            throw new DIYException("手机号不能为空");
        }
        if (RegexUtils.isPhoneInvalid(phone)) {
            throw new DIYException("手机号格式不正确");
        }
        // 生成验证码
        String uuid = UUID.randomUUID().toString().replace("-", "");
        String code = uuid.substring(0, 6); // 取前 6 位
        // 保存验证码到缓存
        boolean isSaved = redisUtil.setWithExpiration(PreKey + phone, code, 2 * 60);// 设置2分钟过期
        if (!isSaved) {
            throw new DIYException("验证码发送过于频繁，请稍后再试");
        }
        return Result.success(code);
    }

    @Operation(summary = "手机验证码登录")
    @PostMapping("/loginByPhone")
    public Result loginByPhone(@RequestBody ResidentDTO residentDTO) {
        String phone = residentDTO.getPhone();
        String code = residentDTO.getCode();
        if (StrUtil.isBlank(phone) || StrUtil.isBlank(code)) {
            throw new DIYException("手机号或验证码不能为空");
        }
        if (RegexUtils.isPhoneInvalid(phone)) {
            throw new DIYException("手机号格式不正确");
        }
        // 验证码校验
        if (!redisUtil.exists(PreKey + phone)) {
            throw new DIYException("验证码已过期，请重新获取");
        }
        if (!redisUtil.get(PreKey + phone).equals(code)) {
            throw new DIYException("验证码错误");
        }
        // 获取居民信息
        Resident resident = residentService.lambdaQuery()
                .eq(Resident::getPhone, phone).one();
        if (resident == null)
            throw new DIYException("用户不存在，请先用手机号注册");
        ResidentVO residentVO = BeanUtil.copyProperties(resident, ResidentVO.class);
        Map<String, Object> claims = new HashMap<>();
        claims.put("residentId", resident.getId());
        claims.put("account", resident.getAccount());
        String token = JwtUtil.getToken(claims, jwtConfig.getResidentTtl(), jwtConfig.getResidentSecretKey());
        residentVO.setToken(token);
        return Result.success(residentVO);
    }

    @Operation(summary = "查看个人资料")
    @GetMapping("/myInfo")
    public Result myInfo() {
        if (ResidentContext.getCurrentId() == null) throw new DIYException("请先登录");
        Long userId = ResidentContext.getCurrentId();
        Resident resident = residentService.lambdaQuery()
                .eq(Resident::getId, userId)
                .one();
        if (resident == null) throw new DIYException("用户不存在");
        return Result.success(resident);
    }
    @Operation(summary = "修改个人资料")
    @PostMapping("/updateInfo")
    public Result updateInfo(@RequestBody ResidentDTO residentDTO) {
        if (ResidentContext.getCurrentId() == null) throw new DIYException("请先登录");
        Long userId = ResidentContext.getCurrentId();
        Resident resident = residentService.lambdaQuery()
                .eq(Resident::getId, userId)
                .one();
        if (resident == null) throw new DIYException("用户不存在");
        BeanUtils.copyProperties(residentDTO, resident);
        resident.setUpdateTime(LocalDateTime.now());
        residentService.updateById(resident);
        return Result.success();
    }
}
